/*
 *Copyright (c) [2019-2020]  C2comm, Inc.  All rights reserved.
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; If not, see <https://www.gnu.org/licenses/>
 */
/*
 *Vendor: C2comm
 *Version: 1.0
 *Filename: SMUnsync.v
 *Target Device: Altera
 *Author : sunxiaotian@c2comm.cn
*/

module SMUnsync(
input  wire         SYS2CORE_clk,
input  wire         SYS2CORE_rst_n,
input  wire         GA2SU_guard_pcf_valid,
input  wire [3:0]   GA2SU_guard_pcf,
output reg          SU2GA_guard_pcf_ready,
input  wire         GA2SU_guard_timeout,
input  wire [1:0]   GA2SU_guard_conf,
output reg          SU2CS_cmd_valid,
output reg [7:0]    SU2CS_cmd_next_top_state,
output wire [8:0]   SU2CS_cmd_bottom_state,
input  wire [7:0]   current_top_state,
output reg          SU2CS_cmd_next_top_state_valid    

);

reg [8:0]  SMUnsync_state;

parameter INIT_S=9'b0_0000_0001,
          MATCH_S=9'b0_0000_0010,
          COMPLETE_S=9'b0_0000_0100,
          C0_S=9'b0_0000_1000,
          C1_S=9'b0_0001_0000,
          C2_S=9'b0_0010_0000,
          C3_S=9'b0_0100_0000,
          C4_S=9'b0_1000_0000,
          C5_S=9'b1_0000_0000;
		  
assign SU2CS_cmd_bottom_state={SMUnsync_state};    
     
always@(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n )begin
	if(~SYS2CORE_rst_n)begin
		SU2CS_cmd_valid<=1'b0;
		SU2CS_cmd_next_top_state<=8'd0;
		SU2GA_guard_pcf_ready<=1'b1;
		SU2CS_cmd_next_top_state_valid<=1'b0;
		SMUnsync_state<=INIT_S;
	end 
	else begin
		case(SMUnsync_state)
			INIT_S:begin
				SU2CS_cmd_valid<=1'b0;
				SU2CS_cmd_next_top_state<=8'd0;
				SU2GA_guard_pcf_ready<=1'b1;
				SU2CS_cmd_next_top_state_valid<=1'b0;
				if(current_top_state==8'b0000_0100)begin
					SMUnsync_state<=MATCH_S;
				end 
				else begin
					SMUnsync_state<=INIT_S;           
				end 
			end 
			MATCH_S:begin
				if(GA2SU_guard_pcf[1:0]==2'b00&&GA2SU_guard_pcf_valid==1'b1&&GA2SU_guard_conf[1]==1'b1)begin//00:CS
					SU2GA_guard_pcf_ready<=1'b0;
					SMUnsync_state<=C1_S;
				end 
				else if(GA2SU_guard_pcf[1:0]==2'b00&&GA2SU_guard_pcf_valid==1'b1&&GA2SU_guard_conf[0]==1'b1)begin  //00:CS
					 SU2GA_guard_pcf_ready<=1'b0;
					  SMUnsync_state<=C2_S; 
				end 
				else if(GA2SU_guard_pcf[1:0]==2'b01&&GA2SU_guard_pcf_valid==1'b1)begin //01:CA
					 SU2GA_guard_pcf_ready<=1'b0;
					  SMUnsync_state<=C3_S; 
				end 
				else if(GA2SU_guard_pcf[1:0]==2'b10&&GA2SU_guard_pcf_valid==1'b1&&GA2SU_guard_pcf[2]==1'b1)begin //10:IN
					 SU2GA_guard_pcf_ready<=1'b0;
						SMUnsync_state<=C4_S;
				
				end 
				else if(GA2SU_guard_pcf[1:0]==2'b10&&GA2SU_guard_pcf_valid==1'b1&&GA2SU_guard_pcf[3]==1'b1)begin //10:IN
					SU2GA_guard_pcf_ready<=1'b0;
					SMUnsync_state<=C5_S;
				
				end 
				else if(GA2SU_guard_timeout==1'b1) begin
					SU2GA_guard_pcf_ready<=1'b0;
					SMUnsync_state<=C0_S;
				end 
				else begin
					SMUnsync_state<=MATCH_S;
					SU2GA_guard_pcf_ready<=1'b1;
				end 
			end  
			C0_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b1;
				SU2CS_cmd_next_top_state[7:0]<=8'b0000_0100; //SM_UNSYNC
				SU2GA_guard_pcf_ready<=1'b0;
				SMUnsync_state<=COMPLETE_S;
			end 
			C1_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b1;
				SU2CS_cmd_next_top_state[7:0]<=8'b0000_1000; //SM_FLOOD
				SU2GA_guard_pcf_ready<=1'b0;
				SMUnsync_state<=COMPLETE_S;
			end 
			C2_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b1;
				SU2CS_cmd_next_top_state[7:0]<=8'b0000_1000;//SM_FLOOD
				SU2GA_guard_pcf_ready<=1'b0;
				SMUnsync_state<=COMPLETE_S;
			
			end 
			C3_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b1;
				SU2CS_cmd_next_top_state[7:0]<=8'b0001_0000;//SM_WAIT_4_CYCLE_START_CS
				SU2GA_guard_pcf_ready<=1'b0;
				SMUnsync_state<=COMPLETE_S;
			end 
			C4_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b1;
				SU2CS_cmd_next_top_state[7:0]<=8'b0100_0000;//SM_SYNC
				SU2GA_guard_pcf_ready<=1'b0;
				SMUnsync_state<=COMPLETE_S;
			end 
			C5_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b1;
				SU2CS_cmd_next_top_state[7:0]<=8'b0010_0000;//SM_TENTATIVE
				SU2GA_guard_pcf_ready<=1'b0;
				SMUnsync_state<=COMPLETE_S;
			end 
			COMPLETE_S:begin
				SU2CS_cmd_next_top_state_valid<=1'b0;
				SMUnsync_state<=INIT_S;     
			end 
		
		endcase

	end     
end           
                   
endmodule